package com.study.web.controller;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaIgnore;
import com.study.app.service.IAppLoginService;
import com.study.app.service.IAppUserService;
import com.study.common.annotation.RepeatSubmit;
import com.study.common.core.controller.AppBaseController;
import com.study.common.core.domain.R;
import com.study.common.core.domain.model.AppEmailCodeBody;
import com.study.common.core.domain.model.AppForgetPasswordBody;
import com.study.common.core.domain.model.AppReplacePasswordBody;
import com.study.common.core.domain.model.AppSmsCodeBody;
import com.study.common.utils.AesGcmUtils;
import com.study.common.utils.MessageUtils;
import com.study.common.utils.RedisKeyUtils;
import com.study.common.utils.redis.RedisUtils;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;

/**
 * 修改密码/绑定信息/注销账号
 *
 * @author mjzx
 */
@Slf4j
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping
public class ExchangeController extends AppBaseController {

    private final IAppUserService iAppUserService;
    private final IAppLoginService iAppLoginService;

    /**
     * 修改密码
     *
     * @param replacePasswordBody 绑定信息
     * @return 结果
     */
    @RepeatSubmit()
    @SaCheckLogin
    @PostMapping("/replacePassword")
    public R<Void> replacePassword(@Validated @RequestBody AppReplacePasswordBody replacePasswordBody) {
        replacePasswordBody.setNewPassword(iAppLoginService.decrypt(replacePasswordBody.getNewPassword()));
        replacePasswordBody.setOldPassword(iAppLoginService.decrypt(replacePasswordBody.getOldPassword()));
        iAppUserService.replacePassword(getUserId(), replacePasswordBody);
        return R.ok();
    }

    /**
     * 手机号绑定
     *
     * @param appSmsCodeBody 绑定信息
     * @return 结果
     */
    @RepeatSubmit()
    @SaCheckLogin
    @PostMapping("/bindPhone")
    public R<Void> bindPhone(@Validated @RequestBody AppSmsCodeBody appSmsCodeBody) {
        iAppUserService.bindPhone(getUserId(), appSmsCodeBody);
        return R.ok();
    }

    /**
     * 更换绑定手机号
     *
     * @param appSmsCodeBody 更换信息
     * @return 结果
     */
    @RepeatSubmit()
    @SaCheckLogin
    @PostMapping("/exchangePhone")
    public R<Void> exchangePhone(@Validated @RequestBody AppSmsCodeBody appSmsCodeBody) {
        iAppUserService.exchangePhone(getUserId(), appSmsCodeBody);
        return R.ok();
    }
    /**
     * 验证更换绑定手机号验证码
     *
     * @return 结果
     */
    @RepeatSubmit()
    @SaCheckLogin
    @SneakyThrows
    @GetMapping("/checkExchangeSmsCode")
    public R<Void> checkExchangeSmsCode(@RequestParam @NotNull String code) {
        String phone = AesGcmUtils.decrypt(getUserPhone());
        String key = RedisKeyUtils.getAppSmsExchangeCode(phone);

        if (!RedisUtils.hasKey(key)) {
            return R.fail(MessageUtils.message("verification.code.phone.expired"));
        }
        String value = RedisUtils.getCacheObject(key);

        if (!code.equals(value)) {
            return R.fail(MessageUtils.message("verification.code.phone.error"));
        }
        RedisUtils.deleteObject(key);

        return R.ok();
    }

    /**
     * 验证更换绑定邮箱验证码
     *
     * @return 结果
     */
    @RepeatSubmit()
    @SaCheckLogin
    @SneakyThrows
    @GetMapping("/checkExchangeMailCode")
    public R<Void> checkExchangeMailCode(@RequestParam @NotNull String code) {
        String email = AesGcmUtils.decrypt(getUserEmail());
        String key = RedisKeyUtils.getAppSmsExchangeCurrentCode(email);

        if (!RedisUtils.hasKey(key)) {
            return R.fail(MessageUtils.message("verification.code.email.expired"));
        }
        String value = RedisUtils.getCacheObject(key);

        if (!code.equals(value)) {
            return R.fail(MessageUtils.message("verification.code.email.error"));
        }
        RedisUtils.deleteObject(key);
        return R.ok();
    }

    /**
     * 更换绑定邮箱
     *
     * @param appEmailCodeBody 更换信息
     * @return 结果
     */
    @RepeatSubmit()
    @SaCheckLogin
    @PostMapping("/exchangeMail")
    public R<Void> exchangeMail(@Validated @RequestBody AppEmailCodeBody appEmailCodeBody) {
        iAppUserService.exchangeMail(getUserId(), appEmailCodeBody);
        return R.ok();
    }

    /**
     * 设置账号密码
     *
     * @param password 密码超过6位数，限制最大长度20位，必须由数字、字母、符号其中两种组成（加密）
     * @return 结果
     */
    @RepeatSubmit()
    @SaCheckLogin
    @PostMapping("/setPassword")
    public R<Void> setPassword(@Validated @NotBlank @Pattern(regexp = "(?![0-9]+$)(?![a-z]+$)(?![A-Z]+$)(?!([^(0-9a-zA-Z)])+$).{6,20}",
            message = "exchange.password.exceeds.digits") @RequestParam String password) {
        String decryptPassword = iAppLoginService.decrypt(password);
        iAppUserService.setPassword(getUserId(), decryptPassword);
        return R.ok();
    }

    /**
     * 忘记密码修改 - 短信
     *
     * @param appForgetPasswordBody 信息
     * @return 结果
     */
    @RepeatSubmit()
    @SaIgnore
    @PostMapping("/smsExchangePassword")
    public R<Void> smsForgetPassword(@Validated @RequestBody AppForgetPasswordBody appForgetPasswordBody) {
//        appForgetPasswordBody.setPassword(iAppLoginService.decrypt(appForgetPasswordBody.getPassword()));
        iAppUserService.smsExchangePassword(appForgetPasswordBody);
        return R.ok();
    }

    /**
     * 忘记密码修改 - 邮箱
     *
     * @param appForgetPasswordBody 信息
     * @return 结果
     */
    @RepeatSubmit()
    @SaIgnore
    @PostMapping("/emailExchangePassword")
    public R<Void> emailExchangePassword(@Validated @RequestBody AppForgetPasswordBody appForgetPasswordBody) {
        appForgetPasswordBody.setPassword(iAppLoginService.decrypt(appForgetPasswordBody.getPassword()));
        iAppUserService.emailExchangePassword(getUserId(), appForgetPasswordBody);
        return R.ok();
    }

    /**
     * 永久注销账号-不可逆
     *
     * @param appSmsCodeBody 注销信息
     * @return 结果
     */
    @RepeatSubmit()
    @SaCheckLogin
    @PostMapping("/logOff")
    public R<Void> logOff(@Validated @RequestBody AppSmsCodeBody appSmsCodeBody) {
        iAppUserService.logOff(getAppLoginUser(), appSmsCodeBody);
        return R.ok();
    }

    /**
     * 永久注销账号-不可逆
     *
     * @param appEmailCodeBody 注销信息
     * @return 结果
     */
    @RepeatSubmit()
    @SaCheckLogin
    @PostMapping("/logOffEmail")
    public R<Void> logOffEmail(@Validated @RequestBody AppEmailCodeBody appEmailCodeBody) {
        //同步清除用户的车辆信息、、骑行记录、告警消息、、

        iAppUserService.logOffEmail(getAppLoginUser(), appEmailCodeBody);
        return R.ok();
    }

}
